package gui;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.Date;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.EtchedBorder;
import javax.swing.border.TitledBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;

import users.Customer;

public class PurchaseOnline extends JPanel{
	
	private static final long serialVersionUID = -1037695349420557599L;

	private Customer cust;
	
	private JPanel lPanel = null;
	private JPanel loPanel = null;
	private JPanel iPanel = null;
	private JPanel bPanel = null;
	private JPanel cPanel = null;
	private JTable iTable = null;
	private JTable bTable = null;
	DefaultTableModel bModel = null;
	private JTextField cidText, pText, qty, cardNum, cardExpiry;
	private JButton loginButton, logoutButton, addToBasketButton, rmFromBasketButton, checkoutButton;
	private JButton sendOrder;
	private String cID = null, pWrd = null;
	private int itemRow = -1;
	private int basketRow = -1;
	private JTextArea confirmOrder;

	// search panel related elements
	private JPanel adder = null;
	private JTextField singerText;
	private JTextField titleText;
	private JTextField catText;
	private JButton searchB;
	private JTextField quantityText;
	private JButton refreshAll;
	private JTable myTable;
	
	// the main panel
	public PurchaseOnline(Customer cust) {
		this.cust = cust;
		
		setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
		
		loginPanel();
	}
	
	// login panel
	private void loginPanel() {
		lPanel = new JPanel(new FlowLayout());
		lPanel.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED));
		
		lPanel.add(new JLabel("Customer ID: "));
        cidText = new JTextField();
        cidText.setPreferredSize(new Dimension(220, 30));
        lPanel.add(cidText);

        lPanel.add(new JLabel("Password: "));
        pText = new JTextField();
        pText.setPreferredSize(new Dimension(220, 30));
        lPanel.add(pText);
        
		loginButton = new JButton("Login");
		loginButton.addActionListener(new verifyLogin());
		lPanel.add(loginButton);
		
		add(lPanel);
	}
	
	// logout button
	private void logoutPanel() {
		loPanel = new JPanel(new FlowLayout());
		
		loPanel.add(new JLabel("Press button to logout:"));
		logoutButton = new JButton("Logout");
		logoutButton.addActionListener(new verifyLogout());
		loPanel.add(logoutButton);
		
		add(loPanel);
	}

	// the items panel
	private void itemsPanel(){
		iPanel = new JPanel(new BorderLayout());
		JPanel buttonPanel = new JPanel(new GridLayout(3,3,10,0));
		TitledBorder title = BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), "Items List");
		iPanel.setBorder(title);
		
		// The column names of the item table
		String[] columnNames = {"upc",
								"title",
								"type",
								"category",
								"company",
								"year",
								"sellPrice"};
		
		
		// query Items table and get ResultSet
		ResultSet result = null;
		try {
			result = cust.allItems();
		} catch (SQLException e1) {
			System.out.println("Could not query Items Table.");
			e1.printStackTrace();
		}
		
		// turn ResultSet into a JTable
		try {
			iTable = rsToTable(result, columnNames);
			result.close();
		} catch (SQLException e) {
			System.out.println("Could not query Items Table.");
			e.printStackTrace();
		}
        
		// add a scrolling panel
		JScrollPane scrollPane = new JScrollPane(iTable);
		scrollPane.setSize(500, 50);
        iPanel.add(scrollPane);
        
        // action listener for the table
        iTable.getSelectionModel().addListSelectionListener(new RowListener());
        
        // quantity text label and text field
		buttonPanel.add(new JLabel("Quantity To Order:"));
        qty = new JTextField();
        buttonPanel.add(qty);
        // add to basket button
        addToBasketButton = new JButton("Add To Basket");
        addToBasketButton.addActionListener(new basketAdder());
		buttonPanel.add(addToBasketButton);
        
		iPanel.add(buttonPanel, BorderLayout.LINE_END);
		
		add(iPanel);
	}

	// searching the items
	private void searchPanel(){
		
		adder = new JPanel(new GridLayout(5, 2));
		TitledBorder title = BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), "SEARCH");
		adder.setBorder(title);
		
		adder.add(new JLabel("MUST PROVIDE ONE OF SINGER, CATEGORY, AND TITLE ALONG WITH A QUANTITY"));
		adder.add(new JLabel("OR ALL THREE FIELDS WITH QUANTITY"));
		adder.add(new JLabel("Category:"));
		catText = new JTextField();
		adder.add(catText);

		adder.add(new JLabel("Title:"));
		titleText = new JTextField();
		adder.add(titleText);

		adder.add(new JLabel("Singer:"));
		singerText = new JTextField();
		adder.add(singerText);

		adder.add(new JLabel("Click to Search"));
		searchB = new JButton("Search");
		searchB.addActionListener(new searchB());
		adder.add(searchB);
		
		add(adder);
	}
	
	// item basket panel
	private void basketPanel() {
		// create the main panels to add elements to
		bPanel = new JPanel(new BorderLayout());
		JPanel buttonPanel = new JPanel(new GridLayout(1,2,10,0));
		TitledBorder title = BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), "Shopping Basket");
		bPanel.setBorder(title);
		
		// create the table
		bModel= new DefaultTableModel();
		bTable = new JTable(bModel);
		
		// set the column names
		bModel.addColumn("upc");
		bModel.addColumn("title");
		bModel.addColumn("type");
		bModel.addColumn("category");
		bModel.addColumn("company");
		bModel.addColumn("year");
		bModel.addColumn("sellPrice");
		bModel.addColumn("quantity");
		
		JScrollPane scrollPane = new JScrollPane(bTable);
        bPanel.add(scrollPane,BorderLayout.CENTER);
        
        bTable.getSelectionModel().addListSelectionListener(new RowListener());
		
        // remove from basket button
        rmFromBasketButton = new JButton("Remove From Basket");
        rmFromBasketButton.addActionListener(new basketRemover());
		buttonPanel.add(rmFromBasketButton);
        // remove from basket button
        checkoutButton = new JButton("Checkout");
        checkoutButton.addActionListener(new checkoutBasket());
        buttonPanel.add(checkoutButton);
		
        
        bPanel.add(buttonPanel, BorderLayout.PAGE_END);
		add(bPanel);
	}
	
	// checkout panel
	private void checkoutPanel() {
		// set up the main window
		cPanel = new JPanel(new GridLayout(2,1));
		JPanel buttonPanel = new JPanel(new GridLayout(4,2,5,5));
		TitledBorder title = BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), "Items to Purchase");
		cPanel.setBorder(title);
		
		// add the basket to the panel
		JScrollPane scrollPane = new JScrollPane(bTable);
        cPanel.add(scrollPane);
        
        // get total cost of items in the basket
        String totalCost = findTotalCost(bTable);
        
        // show the total cost
        buttonPanel.add(new JLabel("Total Amount Due:"));
        JTextArea amount = new JTextArea();
        amount.setEditable(false);
        amount.append(totalCost);
        buttonPanel.add(amount);
		
        // textfield for the credit card number
        buttonPanel.add(new JLabel("Please input your Credit Card #:"));
        cardNum = new JTextField();
        buttonPanel.add(cardNum);
        
        // textfield for credit card's expiry date
        buttonPanel.add(new JLabel("Please input your Credit Card #'s Expiry Date: (ex. YYYY-MM-DD = 2008-01-01)"));
        cardExpiry = new JTextField();
        buttonPanel.add(cardExpiry);
        
        // send order button
        sendOrder = new JButton("Send Order");
        sendOrder.addActionListener(new sendOrder());
        buttonPanel.add(sendOrder);
        
        confirmOrder = new JTextArea();
        buttonPanel.add(confirmOrder);
        
        cPanel.add(buttonPanel);
        
		add(cPanel);
	}
	
	// update the items panel
	private void updateAll(ResultSet rs) throws SQLException{
		iPanel.removeAll();
		
		String[] columnNames = {"upc",
								"title",
								"type",
								"category",
								"company",
								"year",
								"sellPrice"};
		
		iTable.removeAll();
		iTable.validate();
		iTable = rsToTable(rs, columnNames);
		
		// add a scrolling panel
		JScrollPane scrollPane = new JScrollPane(iTable);
		scrollPane.setSize(500, 50);
        iPanel.add(scrollPane);
        
        // action listener for the table
        iTable.getSelectionModel().addListSelectionListener(new RowListener());
        
        // quantity text label and text field
        JPanel buttonPanel = new JPanel(new GridLayout(3,3,10,0));
		buttonPanel.add(new JLabel("Quantity To Order:"));
        qty = new JTextField();
        buttonPanel.add(qty);
        // add to basket button
        addToBasketButton = new JButton("Add To Basket");
        addToBasketButton.addActionListener(new basketAdder());
		buttonPanel.add(addToBasketButton);
        
		iPanel.add(buttonPanel, BorderLayout.LINE_END);
		
		iPanel.validate();
	}
	
	// action listener for the Seach
	private class searchB implements ActionListener {
		String category, singer, title;
		int quantity;
		ResultSet rs2;
		public void actionPerformed(ActionEvent arg0) {
			category = catText.getText();
			singer = singerText.getText();
			title = titleText.getText();
			
			try {
				rs2 = cust.searchItem(singer, category, title);
				updateAll(rs2);
				
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	// refresh all windows
	public class refreshAll implements ActionListener {
		public void actionPerformed(ActionEvent e9) {
			removeAll();
			
			logoutPanel();
			searchPanel();
			itemsPanel();
			basketPanel();
			checkoutPanel();
		}
	}
	
	// action listener for the login button
	private class verifyLogin implements ActionListener {
		
		public void actionPerformed(ActionEvent e0) {
			cID = cidText.getText();
			pWrd = pText.getText();
			
			if(cID.isEmpty() || pWrd.isEmpty()) {
				JOptionPane.showMessageDialog(loginButton,
					    "Please check that the following have been entered:\n- Customer ID\n- Password",
					    "Login Error",
					    JOptionPane.ERROR_MESSAGE);
			} else {
				boolean success = false;
				
				try {
					success = cust.findCustomer(cID, pWrd);
				} catch (SQLException e1) {
					JOptionPane.showMessageDialog(loginButton,
						    "Customer ID and Password do not match.\nPlease re-enter your Customer ID and Password or Please Register.",
						    "Login Error",
						    JOptionPane.ERROR_MESSAGE);
				}
				
				// if login is successful, create the purchasing panels
				if(success == true) {
					lPanel.setVisible(false);
					logoutPanel();
					searchPanel();
					itemsPanel();
					basketPanel();
				} else {
					JOptionPane.showMessageDialog(loginButton,
						    "Customer ID and Password do not match.\nPlease re-enter your Customer ID and Password or Please Register.",
						    "Login Error",
						    JOptionPane.ERROR_MESSAGE);
				}
			}
		}
	}
	
	// action listener for the logout button
	private class verifyLogout implements ActionListener {
		
		public void actionPerformed(ActionEvent e1) {
			
			//set items and basket panels invisible
			iPanel.setVisible(false);
			bPanel.setVisible(false);
			
			// remove the items and basket panels
			removeAll();
			
			// recreate the login
			loginPanel();
		}
				
	}

	// action listener for the item table selector
	private class RowListener implements ListSelectionListener {
		
		public void valueChanged(ListSelectionEvent e2) {
            if (e2.getValueIsAdjusting()) {
                return;
            }
			
            // get the item that is selected from the item table
            itemRow = iTable.getSelectedRow();
            basketRow = bTable.getSelectedRow();
            System.out.print("Selected Item Row: " + itemRow);
            System.out.println(", Selected Basket Row: " + basketRow);
		}
	}
	
	// action listener for the "Add to Basket" button
	private class basketAdder implements ActionListener {
		
		String qtyString, itemUPC;
		int quantity, stockQty;
		
		public void actionPerformed(ActionEvent e3) {
			// get the quantity
			qtyString = qty.getText();
			
			// show an error window (no quantity) if the quantity is nothing
			if(qtyString.isEmpty()) {
				JOptionPane.showMessageDialog(addToBasketButton,
					    "Please enter a quantity to purchase.",
					    "Item Quantity Error",
					    JOptionPane.ERROR_MESSAGE);
						return;
			}
			
			// change quantity to an integer
			quantity = Integer.valueOf(qtyString);
			
			// show an error window if the quantity is less than 1
			if(quantity < 1) {
				JOptionPane.showMessageDialog(addToBasketButton,
					    "Please enter a quantity that is greater than 0.",
					    "Item Quantity Error",
					    JOptionPane.ERROR_MESSAGE);
						return;
			}
			
			// show an error window (no item selection) or add item to the basket table
			if(itemRow == -1) {
				JOptionPane.showMessageDialog(addToBasketButton,
					    "Please select an item to add to the Basket.",
					    "Item Selection Error",
					    JOptionPane.ERROR_MESSAGE);
						return;
			}
				
			// get the item stock
			itemUPC = (String) iTable.getValueAt(itemRow, 0);
			try {
				stockQty = cust.getItemQuantity(itemUPC);
				
				// for debugging
				System.out.println("Amount in warehouse: " + stockQty);
			} catch (SQLException e) {
				JOptionPane.showMessageDialog(addToBasketButton,
					    "There is no stock left for this item. Please select another item.",
					    "Insufficient Item Quantity Error",
					    JOptionPane.ERROR_MESSAGE);
						return;
			}
			
			// if the stock is 0 or is the quantity requested is more than the stock quantity print error messages
			if(stockQty < 1) {
				JOptionPane.showMessageDialog(addToBasketButton,
						"There is no stock left for this item. Please select another item.",
					    "Insufficient Item Quantity Error",
					    JOptionPane.ERROR_MESSAGE);
						return;
			} else if (stockQty < quantity) {
				JOptionPane.showMessageDialog(addToBasketButton,
						"There is not enough stock left for this item.\n" +
					    "Please reduce quantity to " + stockQty + " and retry the 'Add to Basket' button.",
					    "Insufficient Item Quantity Error",
					    JOptionPane.ERROR_MESSAGE);
						return;
			}
			
			
			// for debugging
			System.out.println("Item Table Row: " + itemRow + ", qty: " + quantity);
			
			// update the basket table
			inputToBasket(iTable, bModel, itemRow, quantity);
		}	
	}
	
	// action listener for removing from the basket table
	private class basketRemover implements ActionListener {
		
		public void actionPerformed(ActionEvent e4) {
			// show an error message (no item selected) or remove an item from the basket table
			if(basketRow == -1){
				JOptionPane.showMessageDialog(rmFromBasketButton,
				 "Please select an item to delete from the Basket.",
				    "Item Deletion Error",
				    JOptionPane.ERROR_MESSAGE);
					return;
			} else {
				bModel.removeRow(basketRow);
			}
		}
	}
	
	// action listener for checking out a basket
	private class checkoutBasket implements ActionListener {

		public void actionPerformed(ActionEvent e5) {
			// set all other panels invisible
			iPanel.setVisible(false);
			bPanel.setVisible(false);
			adder.setVisible(false);
			
			// create the checkout panel
			checkoutPanel();
		}
	}
	
	// action listener for sending an order from the checkout
	private class sendOrder implements ActionListener {
		private String cDate, cname;
		private Object upc, qty;
		private int rid = 0, cNum = 0;
		private Date estDate, today = new Date(System.currentTimeMillis());
		private ResultSet customer = null;
		
		public void actionPerformed(ActionEvent e6) {
			cNum = Integer.valueOf(cardNum.getText());
			cDate = cardExpiry.getText();
			
			//get customer name
			try {
				customer = cust.retrieveUserStats(cID, pWrd);
				
				if(customer.next()) {
					cname = customer.getString(3);
				} else {
					cname = null;
				}
			} catch (SQLException e) {
				System.out.println("Could not get customer name.");
			}
			
			// get expectedDate and receiptID
			estDate = cust.findEstimatedDate();
			rid = cust.getRID();
			
			
			// insert into purchase table
			cust.addToPurchase(rid, today, cID, cname, cNum, cDate, estDate);
			
			for(int i = 0; i < bTable.getRowCount(); i++) {
				upc = bTable.getValueAt(i, 0).toString();
				qty = bTable.getValueAt(i, 7);
				
				// insert into purchase item table
				cust.addToPurchaseItem(rid, upc, qty);
			}
			
			confirmOrder.append("Order Sent. Expected Delivery Date: " + estDate); 
		}
	}
	
	// make a JTable from a ResultSet
	private static JTable rsToTable(ResultSet result, String[] columnNames) throws SQLException{
		List<Object[]> rows = new ArrayList<Object[]>();
		
		while (result.next()){
			Object[] row = new Object[columnNames.length+1];
			
			for (int i=0; i<columnNames.length; i++){
				Object value = result.getObject(columnNames[i]);
				row[i] = value;
			}			
			rows.add(row);
		}
		
		Object[][] data = new Object[rows.size()][columnNames.length+1];
		
		for (int i=0; i<rows.size(); i++){
			data[i] = rows.get(i);
		}
		
		JTable table = new JTable(data, columnNames);
		table.setPreferredScrollableViewportSize(new Dimension(500, 70));
        table.setFillsViewportHeight(true);
		
		return table;
	}
	
	// add items to the basket
	private void inputToBasket(JTable in, DefaultTableModel out, int row, int qty){
		
		Object upc, tle, typ, cat, com, yr, sP;
		int totalQty, stockQty = 0;
		boolean alreadyAdded = false;
		
		// get the cells to input into the basket table
		upc = in.getValueAt(row, 0);
		tle = in.getValueAt(row, 1);
		typ = in.getValueAt(row, 2);
		cat = in.getValueAt(row, 3);
		com = in.getValueAt(row, 4);
		yr =  in.getValueAt(row, 5);
		sP =  in.getValueAt(row, 6);
		
		// update quantity if user already has the item in the basket
		for (int i = 0; i < out.getRowCount(); i++) {
			if(upc == out.getValueAt(i, 0)) {
				try {
					stockQty = cust.getItemQuantity((String) upc);
				} catch (SQLException e) {
					e.printStackTrace();
				}
				totalQty = (Integer) out.getValueAt(i, 7) + qty;
				
				// print error messages if there is not enough stock else add the quantity to the item in the basket
				if (stockQty == (Integer) out.getValueAt(i, 7)){
					JOptionPane.showMessageDialog(addToBasketButton,
							"There is not enough stock left for this item.\n" +
						    "Please select a different item to purchase.",
						    "Insufficient Item Quantity Error",
						    JOptionPane.ERROR_MESSAGE);
				
				} else if( stockQty < totalQty) {
					JOptionPane.showMessageDialog(addToBasketButton,
					"There is not enough stock left for this item.\n" +
				    "Please reduce quantity to " +  (stockQty - (Integer) out.getValueAt(i, 7)) + " and retry the 'Add to Basket' button.",
				    "Insufficient Item Quantity Error",
				    JOptionPane.ERROR_MESSAGE);
					
				} else {
					out.setValueAt(totalQty, i, 7);
				}
				
				alreadyAdded = true;
			}
		}
		
		// if item has not been added, add it to the basket table
		if(alreadyAdded == false) {
			out.addRow(new Object[]{upc, tle, typ, cat, com, yr, sP, qty});
		}
	}

	// calculates the total cost of items in the basket
	private String findTotalCost(JTable table) {
		int rowNum = table.getRowCount();
		double cost = 0, prce = 0, qty = 0;
		String costString = null;
		
		
		for(int i = 0; i < rowNum; i++){
			prce =  Double.parseDouble(table.getValueAt(i, 6).toString());
			qty = Double.parseDouble(table.getValueAt(i, 7).toString());
			cost = cost + (prce * qty);
		}
		
		costString = "$" + (cost/100);
		
		System.out.println("Total cost of items: " + costString);
		return costString;
	}
}
